package com.csaba.connector.otp.parser;

import java.io.IOException;
import java.io.Reader;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

import net.htmlparser.jericho.Element;
import net.htmlparser.jericho.HTMLElementName;
import net.htmlparser.jericho.Source;
import net.htmlparser.jericho.TextExtractor;

import com.csaba.connector.model.Account;
import com.csaba.connector.model.Amount;
import com.csaba.connector.model.HistoryItem;
import com.csaba.connector.otp.model.OTPHistoryItem;

public class AccountHistoryParser
{
	private static final String INDICATOR_OK = "eredmenytabla";
	private static final String ERROR_INDICATOR = "hiba";

	public static HistoryItem[] parseAccountHistoryList( final Reader reader, final Account account )
			throws IOException, ParseException
	{
		final Source source = new Source(reader);

		// find the account table
		Element table = source.getNextElement(0, "class", "eredmenytabla", false);
		while ( table != null && !table.getStartTag().getName().equals(HTMLElementName.TABLE) )
		{
			table = source.getNextElement(table.getBegin(), "class", "eredmenytabla", false);
		}
		if ( table == null )
			throw new ParseException("Missing result table for account list.", 0);

		// get body
		final Element tbody = table.getAllElements(HTMLElementName.TBODY).get(0);
		if ( tbody == null )
			throw new ParseException("Unexpected table structure. TBODY is missing.", table.getBegin());
		final List<Element> trs = tbody.getChildElements();
		if ( trs == null || trs.size() == 0 )
			return new OTPHistoryItem[0];

		final HistoryItem[] result = new OTPHistoryItem[trs.size()];

		for ( int i = 0; i < trs.size(); i++ )
		{
			final Element tr = trs.get(i);

			final List<Element> fields = tr.getChildElements();
			/*	
			<thead>
				<tr>
					<th>&nbsp;</th> //sequence number
					<th><a...>Forgalom típusa</a></th>
					<th><a...>Könyvelési dátum</a></th>
					<th><a...>Értéknap</a></th>
					<th><a...>Összeg</a></th>
					<th><a...>Új könyvelt egyenleg</a></th>
					<th><a...>Ellenoldali számlaszám</a></th>
					<th><a...>Ellenoldali név</a></th>
					<th><a...>Közlemény</a></th>
				</tr>
			</thead>
			 */
			if ( fields.size() < 9 )
			{
				throw new ParseException("Invalid account history list structure. Missing columns:" + fields.size(),
						tr.getBegin());
			}
			result[i] = new OTPHistoryItem();

			//parse account fields
			//	skip sequence
			final String trType = new TextExtractor(fields.get(1)).toString();
			final String bookingDateString = new TextExtractor(fields.get(2)).toString().trim();
			final String valueDateString = new TextExtractor(fields.get(3)).toString().trim();
			final String amountString = new TextExtractor(fields.get(4)).toString().trim();
			final String runningBalanceString = new TextExtractor(fields.get(5)).toString().trim();
			final String partnerAccount = new TextExtractor(fields.get(6)).toString().trim();
			final String partnerName = new TextExtractor(fields.get(7)).toString().trim();
			final String description = new TextExtractor(fields.get(8)).toString().trim();

			/*
				<tr class="paros">
					<td>1.</td>
					<td>HAVI ZÁRLATI DÍJ</td>
					<td>2008.05.23.&nbsp;</td>
					<td>2008.05.23.&nbsp;</td>
					<td nowrap="nowrap" class="numerikus">-599</td>
					<td nowrap="nowrap" class="numerikus">6.939</td>
					<td>&nbsp; &nbsp; &nbsp;</td>
					<td>&nbsp;</td>
					<td></td>
				</tr>
			 */

			//processing amounts
			final DecimalFormat amountFormat = OTPCodes.amountFormat.get();
			final double amount = amountFormat.parse(amountString).doubleValue();
			final double runningBalance = amountFormat.parse(runningBalanceString).doubleValue();

			//processing dates
			final SimpleDateFormat dateFormat = OTPCodes.dateFormat.get();
			final Date value = dateFormat.parse(valueDateString);
			final Date booking = dateFormat.parse(bookingDateString);

			result[i].setOwner(account);
			result[i].setAmount(new Amount(amount, account.getCurrency()));
			result[i].setBalance(new Amount(runningBalance, account.getCurrency()));
			result[i].setDate(booking);
			result[i].setDescription(trType);

			result[i].setRemoteProperty("valueDate", value);
			if ( partnerAccount.length() > 0 )
				result[i].setRemoteProperty("partner.account", partnerAccount);
			if ( partnerName.length() > 0 )
				result[i].setRemoteProperty("partner.name", partnerName);
			if ( description.length() > 0 )
				result[i].setRemoteProperty("description", description);

		}

		return result;
	}

	public static boolean isParsable( final String result )
	{
		return result.contains(INDICATOR_OK);
	}

	public static boolean isFailed( final String result )
	{
		return result.contains(ERROR_INDICATOR);
	}
}
